<?php

class User extends ActiveRecord
{
	
    /**
     * @access private
     */
    var $__initial_attributes = array();
    var $__requires_password_confirmation = false;

    /**
     * We need to get initial values when instantiating to know if attributes like password have been changed
     */
    function __construct()
    {
    	$this->setTableName("login");
    	$this->setPrimaryKey("memberid");
        $attributes = (array)func_get_args();
        $this->__initial_attributes = isset($attributes[1]) && is_array($attributes[1]) ? $attributes[1] : array();
        return $this->init($attributes);
    }


    /**
     * Main authentication method
     * 
     * @param string $login
     * @param string $password
     * @return False if not found or not enabled, User instance if succedes
     */
    function authenticate($email, $password)
    {
        $UserInstance =& new User();
        if($User =& $UserInstance->find('first', array('conditions'=>array('email = ?', $email))) && $User->isValidPassword($password)){
            $User->set('last_login_at', Ak::getDate());
            $User->save();
            return $User;
        }
        return false;
    }


    // Validation
    // ---------------

    function validate()
    {
        $this->validatesUniquenessOf('email', array('message'=>$this->t('email %email already in use', array('%email'=>$this->get('email')))));
        $this->validatesUniquenessOf('phone', array('message'=>$this->t('phone already in use')));
        $this->validatesPresenceOf(array('email','phone'));
        $this->validatesFormatOf('email', AK_EMAIL_REGULAR_EXPRESSION, $this->t('Invalid email address'));
        $this->validatesLengthOf('phone', array('in'=>array(9, 20), 'too_long' => $this->t('pick a shorter phone'), 'too_short' => $this->t('pick a longer phone')));
        $this->validatesLengthOf('password', array('in'=>array(4, 40), 'too_long' => $this->t('pick a shorter password'), 'too_short' => $this->t('pick a longer password')));
    }

    function validatesPassword()
    {
        $requires_password_confirmation = $this->hasAttributeBeenModified('password') ? $this->__requires_password_confirmation : false;
        $this->validatesPresenceOf($requires_password_confirmation ? array('password','password_confirmation') : array('password'));
        $requires_password_confirmation ? $this->validatesConfirmationOf('password', $this->t('Must match confirmation')) : null;
        return strlen($this->getErrorsOn('password').$this->getErrorsOn('password_confirmation')) == 0;
    }

    function needsPasswordLengthValidation()
    {
        return $this->isNewRecord() || !empty($this->password);
    }

    function needsEmailValidation()
    {
        return empty($this->_byspass_email_validation);
    }

    function validatesExistanceOfOriginalPasswordWhenUpdatingLogin()
    {
        if($this->hasAttributeBeenModified('login')){
            if(!$this->isValidPassword($this->get('password'), true, true)){
                $this->addError('login', $this->t('can\' be modified unless you provide a valid password.'));
            }else{
                $this->set('password_confirmation', $this->get('password'));
            }
        }
    }

    function isValidPassword($password, $hash_password = true, $hash_using_original_name = false)
    {
        return $this->getPreviousValueForAttribute('password') == ($hash_password ? md5($password) : $password);
    }


    // Triggers
    // ---------------

    function beforeCreate()
    {
        $this->validatesPassword();
        $this->encryptPassword();
        return !$this->hasErrors();
    }

    function beforeUpdate()
    {
        $this->validatesExistanceOfOriginalPasswordWhenUpdatingLogin();
        $this->validatesPassword();
        $this->_encryptPasswordUnlessEmptyOrUnchanged();
        return !$this->hasErrors();
    }

    function afterSave()
    {
        $this->__initial_attributes = $this->getAttributes();
        return true;
    }


    // Enabling disabling accounts
    // --------------------------


    function enable()
    {
        $this->updateAttribute('is_enabled', true);
    }

    function disable()
    {
        $this->updateAttribute('is_enabled', false);
    }


    // Inspecting original values
    // --------------------------

    function hasAttributeBeenModified($attribute)
    {
        return $this->getPreviousValueForAttribute($attribute) != $this->get($attribute);
    }

    function getPreviousValueForAttribute($attribute)
    {
        return $this->hasColumn($attribute) && isset($this->__initial_attributes[$attribute]) ? $this->__initial_attributes[$attribute] : null;
    }


    // Hashing
    // -----------------------

    function encryptPassword()
    {
        $this->set('password', md5($this->get('password')));
    }

    function getToken()
    {
        return $this->sha1($this->sha1($this->get('updated_at').$this->get('email')).$this->get('password'));
    }

    function isTokenValid($token)
    {
        return $this->getToken() == $token;
    }

    function _encryptPasswordUnlessEmptyOrUnchanged()
    {
        if($this->hasAttributeBeenModified('password') || $this->get('password') == ''){
            $this->encryptPassword();
        }else{
            $this->set('password', $this->getPreviousValueForAttribute('password'));
        }
    }

	/* util */
	
    function getCurrentUser()
    {
        return User::_setCurrentUser(false);
    }

    function _setCurrentUser($CurrentUser)
    {
        static $_cached;
        if(!empty($CurrentUser)){
            $_cached = $CurrentUser;
        }elseif (empty($_cached)){
            trigger_error(Ak::t('Current user has not been set yet.'), E_USER_ERROR);
        }
        return $_cached;
    }
}

?>
